package com.xsy.glsurfaceview

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.opengl.GLES30
import android.opengl.GLUtils
import android.opengl.Matrix
import android.util.Log
import java.nio.ByteBuffer
import java.nio.ByteOrder


class TextureRender4(bitmap: Bitmap, vertexShaderCode: String, fragmentShaderCode: String) {
    companion object {
        const val vertex_file_path = "vshader/TextureCustom4.glsl"
        const val fragment_file_path = "fshader/TextureCustom4.glsl"
    }


    private val coordData = floatArrayOf(
        //顶点坐标           纹理坐标
        -1.0f, 1.0f, 0.0f, 0.0f, 0.0f,  //左上角
        -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, //左下角
        1.0f, 1.0f, 0.0f, 1.0f, 0.0f,   //右上角
        1.0f, -1.0f, 0.0f, 1.0f, 1.0f   //右下角
    )

    private var translateMatrix = FloatArray(16)

    private var mProgram = -1
    private var mPositionHandle = -1
    private var mTexCoordHandle = -1
    private var mMVPTMatrixHandle = -1
    private var mSamplerHandle = -1

    private var mTextureId = -1

    private val vboId: IntArray = IntArray(1)
    private fun loadShader(type: Int, shaderCode: String): Int {
        val shader = GLES30.glCreateShader(type)
        GLES30.glShaderSource(shader, shaderCode)
        GLES30.glCompileShader(shader)
        return shader
    }

    init {
        mTextureId = uploadTexture(bitmap)
        val bb = ByteBuffer.allocateDirect((coordData.size * 4))
        bb.order(ByteOrder.nativeOrder())
        val coordBuffer = bb.asFloatBuffer()
        coordBuffer.put(coordData)
        coordBuffer.position(0)
        Log.d("MyGLSurfaceView", "fragment shader code: $fragmentShaderCode")
        Log.d("MyGLSurfaceView", "vertex shader code: $vertexShaderCode")
        val vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode)
        val fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode)
        mProgram = GLES30.glCreateProgram()
        GLES30.glAttachShader(mProgram, vertexShader)
        GLES30.glAttachShader(mProgram, fragmentShader)
        GLES30.glLinkProgram(mProgram)
        GLES30.glDeleteShader(vertexShader)
        GLES30.glDeleteShader(fragmentShader)
        GLES30.glGenBuffers(1, vboId, 0)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboId[0])
        GLES30.glBufferData(
            GLES30.GL_ARRAY_BUFFER, bb.capacity(),
            bb, GLES30.GL_STATIC_DRAW
        )
        Matrix.setIdentityM(translateMatrix, 0)
        mPositionHandle = GLES30.glGetAttribLocation(mProgram, "aPosition")
        GLES30.glEnableVertexAttribArray(mPositionHandle)
        checkGlError("aPosition")
        mTexCoordHandle = GLES30.glGetAttribLocation(mProgram, "aTexCoord")
        GLES30.glEnableVertexAttribArray(mTexCoordHandle)
        checkGlError("aTexCoord")
        mMVPTMatrixHandle = GLES30.glGetUniformLocation(mProgram, "uMVPTMatrix")
        checkGlError("uTMatrix")
        mSamplerHandle = GLES30.glGetUniformLocation(mProgram, "uSampler")
        checkGlError("uSampler")
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)
    }

    fun draw(mvpMatrix: FloatArray) {
        //使用program
        GLES30.glUseProgram(mProgram)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboId[0])

        GLES30.glVertexAttribPointer(mPositionHandle, 3, GLES30.GL_FLOAT, false, 5*Float.SIZE_BYTES, 0)
        checkGlError("mPositionHandle")

        GLES30.glVertexAttribPointer(mTexCoordHandle, 2, GLES30.GL_FLOAT, false, 5*Float.SIZE_BYTES, 3*Float.SIZE_BYTES)
        checkGlError("mTexCoordHandle")
        //传入正交矩阵修复变形
        GLES30.glUniformMatrix4fv(mMVPTMatrixHandle, 1, false, mvpMatrix, 0)
        checkGlError("mTMatrixHandle")

        GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureId)
        GLES30.glUniform1i(mSamplerHandle, 0)

        //drawAarray, 绘制矩型
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4)

        // 解绑VBO
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)
    }

    fun onDestroy() {
        GLES30.glDeleteProgram(mProgram)
        GLES30.glDeleteBuffers(1, vboId, 0)
    }


    private fun uploadTexture(bitmap: Bitmap): Int {

        val textureIds = IntArray(1)
        GLES30.glGenTextures(1, textureIds, 0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIds[0])

        GLES30.glTexParameteri(
            GLES30.GL_TEXTURE_2D,
            GLES30.GL_TEXTURE_MIN_FILTER,
            GLES30.GL_LINEAR
        )
        GLES30.glTexParameteri(
            GLES30.GL_TEXTURE_2D,
            GLES30.GL_TEXTURE_MAG_FILTER,
            GLES30.GL_LINEAR
        )

        GLUtils.texImage2D(
            GLES30.GL_TEXTURE_2D,
            0,
            GLES30.GL_RGBA,
            bitmap,
            0
        )
        bitmap.recycle()
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)
        return textureIds[0]
    }

    fun checkGlError(op: String) {
        val error = GLES30.glGetError();

        if (error != GLES30.GL_NO_ERROR) {
            val msg = op + ": glError 0x" + Integer.toHexString(error)
            Log.e("MyGLSurfaceView", msg)
        }
    }


}